<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN"
  "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">

<html xmlns="http://www.w3.org/1999/xhtml">
  <head>
    <meta http-equiv="Content-Type" content="text/html; charset=utf-8" />
    
    <title>composite模式 &mdash; programming v0.1 documentation</title>
    <link rel="stylesheet" href="../_static/default.css" type="text/css" />
    <link rel="stylesheet" href="../_static/pygments.css" type="text/css" />
    <script type="text/javascript">
      var DOCUMENTATION_OPTIONS = {
        URL_ROOT:    '../',
        VERSION:     '0.1',
        COLLAPSE_MODINDEX: false,
        FILE_SUFFIX: '.html',
        HAS_SOURCE:  true
      };
    </script>
    <script type="text/javascript" src="../_static/jquery.js"></script>
    <script type="text/javascript" src="../_static/doctools.js"></script>
    <script type="text/javascript" src="../_static/translations.js"></script>
    <link rel="author" title="关于这些文档" href="../about.html" />
    <link rel="top" title="programming v0.1 documentation" href="../index.html" />
    <link rel="up" title="设计模式学习笔记" href="index.html" />
    <link rel="next" title="state模式" href="state.html" />
    <link rel="prev" title="iterator模式" href="iterator.html" /> 
  </head>
  <body>
    <div class="related">
      <h3>导航</h3>
      <ul>
        <li class="right" style="margin-right: 10px">
          <a href="../genindex.html" title="总目录"
             accesskey="I">索引</a></li>
        <li class="right" >
          <a href="state.html" title="state模式"
             accesskey="N">下一页</a> |</li>
        <li class="right" >
          <a href="iterator.html" title="iterator模式"
             accesskey="P">上一页</a> |</li>
        <li><a href="../index.html">programming v0.1 documentation</a> &raquo;</li>
          <li><a href="index.html" accesskey="U">设计模式学习笔记</a> &raquo;</li> 
      </ul>
    </div>  

    <div class="document">
      <div class="documentwrapper">
        <div class="bodywrapper">
          <div class="body">
            
  <div class="section" id="composite">
<h1>composite模式<a class="headerlink" href="#composite" title="永久链接至标题">¶</a></h1>
<div class="section" id="id1">
<span id="index-3"></span><span id="id2"></span><h2>composite模式定义<a class="headerlink" href="#id1" title="永久链接至标题">¶</a></h2>
<p><strong>The Composite Pattern</strong> allows you to compose objects into tree structures to
represent part-whole hierarchies. Composite lets clients treat individual objects and
compositions of objects uniformly.</p>
<p><strong>组合模式</strong> 使得可以将对象组合为 <strong>树</strong> 结构来表示 <strong>部分-整体</strong> 的层级关系.
组合使得用户能够 <strong>统一</strong> 地对待单一对象和多个对象的组合.</p>
</div>
<div class="section" id="id3">
<h2>问题描述<a class="headerlink" href="#id3" title="永久链接至标题">¶</a></h2>
<p>与 <a class="reference external" href="iterator.html#id1"><em>iterator模式定义</em></a> 中的场景类似,现在的菜单不只是单一的条目,还可能包含子菜单,即:</p>
<ul class="simple">
<li>菜单中可能包含菜单</li>
<li>菜单中可能包含菜单条目</li>
</ul>
<p>整个关系即是一种 <strong>树形</strong> 的结构.</p>
<p>可用下图来表示:</p>
<img alt="../_images/composite_exp.png" src="../_images/composite_exp.png" />
<p>实现时使用的类图为:</p>
<img alt="../_images/composite_exp_class.png" src="../_images/composite_exp_class.png" />
<p><strong>composite模式</strong> 类图如下:</p>
<img alt="../_images/composite_class.png" src="../_images/composite_class.png" />
</div>
<div class="section" id="id4">
<h2>具体代码<a class="headerlink" href="#id4" title="永久链接至标题">¶</a></h2>
<p>下载请点击 <a href="../_downloads/composite.cpp"><strong class="xref">这里</strong></a></p>
<div class="highlight-c++"><table class="highlighttable"><tr><td class="linenos"><pre>  1
  2
  3
  4
  5
  6
  7
  8
  9
 10
 11
 12
 13
 14
 15
 16
 17
 18
 19
 20
 21
 22
 23
 24
 25
 26
 27
 28
 29
 30
 31
 32
 33
 34
 35
 36
 37
 38
 39
 40
 41
 42
 43
 44
 45
 46
 47
 48
 49
 50
 51
 52
 53
 54
 55
 56
 57
 58
 59
 60
 61
 62
 63
 64
 65
 66
 67
 68
 69
 70
 71
 72
 73
 74
 75
 76
 77
 78
 79
 80
 81
 82
 83
 84
 85
 86
 87
 88
 89
 90
 91
 92
 93
 94
 95
 96
 97
 98
 99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150</pre></td><td class="code"><div class="highlight"><pre><span class="cp">#include&lt;iostream&gt;</span>
<span class="cp">#include&lt;string&gt;</span>
<span class="cp">#include&lt;exception&gt;</span>
<span class="cp">#include&lt;vector&gt;</span>
<span class="k">using</span> <span class="k">namespace</span> <span class="n">std</span><span class="p">;</span>

<span class="k">class</span> <span class="nc">UnsupportedOperationException</span><span class="o">:</span><span class="k">public</span> <span class="n">exception</span>
<span class="p">{</span>
    <span class="k">public</span><span class="o">:</span>
        <span class="k">virtual</span> <span class="k">const</span> <span class="kt">char</span><span class="o">*</span> <span class="n">what</span><span class="p">()</span> <span class="k">const</span> <span class="k">throw</span><span class="p">()</span>
        <span class="p">{</span>
            <span class="k">return</span> <span class="s">&quot;Not Supported Operations!&quot;</span><span class="p">;</span>
        <span class="p">}</span>
<span class="p">};</span>

<span class="k">class</span> <span class="nc">MenuComponent</span>
<span class="p">{</span>
    <span class="k">public</span><span class="o">:</span>
        <span class="k">virtual</span> <span class="kt">void</span> <span class="n">add</span><span class="p">(</span><span class="n">MenuComponent</span> <span class="o">*</span><span class="n">menuComponent</span><span class="p">)</span>
        <span class="p">{</span>
            <span class="n">UnsupportedOperationException</span> <span class="n">ex</span><span class="p">;</span>
            <span class="k">throw</span> <span class="n">ex</span><span class="p">;</span>
        <span class="p">}</span>
        <span class="k">virtual</span> <span class="n">MenuComponent</span><span class="o">*</span> <span class="n">getChild</span><span class="p">(</span><span class="kt">int</span> <span class="n">i</span><span class="p">)</span>
        <span class="p">{</span>
            <span class="n">UnsupportedOperationException</span> <span class="n">ex</span><span class="p">;</span>
            <span class="k">throw</span> <span class="n">ex</span><span class="p">;</span>
        <span class="p">}</span>

        <span class="k">virtual</span> <span class="kt">void</span> <span class="n">print</span><span class="p">()</span>
        <span class="p">{</span>
            <span class="n">UnsupportedOperationException</span> <span class="n">ex</span><span class="p">;</span>
            <span class="k">throw</span> <span class="n">ex</span><span class="p">;</span>
        <span class="p">}</span>

        <span class="k">virtual</span> <span class="n">string</span> <span class="n">getName</span><span class="p">()</span>
        <span class="p">{</span>
            <span class="n">UnsupportedOperationException</span> <span class="n">ex</span><span class="p">;</span>
            <span class="k">throw</span> <span class="n">ex</span><span class="p">;</span>
        <span class="p">}</span>

        <span class="k">virtual</span> <span class="kt">double</span> <span class="n">getPrice</span><span class="p">()</span>
        <span class="p">{</span>
            <span class="n">UnsupportedOperationException</span> <span class="n">ex</span><span class="p">;</span>
            <span class="k">throw</span> <span class="n">ex</span><span class="p">;</span>
        <span class="p">}</span>
<span class="p">};</span>

<span class="k">class</span> <span class="nc">MenuItem</span><span class="o">:</span><span class="k">public</span> <span class="n">MenuComponent</span>
<span class="p">{</span>
    <span class="k">public</span><span class="o">:</span>
        <span class="n">string</span> <span class="n">name</span><span class="p">;</span>
        <span class="kt">double</span> <span class="n">price</span><span class="p">;</span>
        <span class="n">MenuItem</span><span class="p">(</span><span class="n">string</span> <span class="n">name</span><span class="p">,</span> <span class="kt">double</span> <span class="n">price</span><span class="p">)</span>
        <span class="p">{</span>
            <span class="k">this</span><span class="o">-&gt;</span><span class="n">name</span> <span class="o">=</span> <span class="n">name</span><span class="p">;</span>
            <span class="k">this</span><span class="o">-&gt;</span><span class="n">price</span> <span class="o">=</span> <span class="n">price</span><span class="p">;</span>
        <span class="p">}</span>

        <span class="kt">double</span> <span class="n">getPrice</span><span class="p">(){</span><span class="k">return</span> <span class="n">price</span><span class="p">;}</span>
        <span class="n">string</span> <span class="n">getName</span><span class="p">(){</span><span class="k">return</span> <span class="n">name</span><span class="p">;}</span>
        <span class="kt">void</span> <span class="n">print</span><span class="p">()</span>
        <span class="p">{</span>
            <span class="n">cout</span><span class="o">&lt;&lt;</span><span class="s">&quot;Name:  &quot;</span><span class="o">&lt;&lt;</span><span class="n">getName</span><span class="p">()</span><span class="o">&lt;&lt;</span><span class="s">&quot;  Price:&quot;</span><span class="o">&lt;&lt;</span><span class="n">getPrice</span><span class="p">()</span><span class="o">&lt;&lt;</span><span class="n">endl</span><span class="p">;</span>
        <span class="p">}</span>
<span class="p">};</span>

<span class="k">class</span> <span class="nc">Menu</span><span class="o">:</span><span class="k">public</span> <span class="n">MenuComponent</span>
<span class="p">{</span>
    <span class="k">public</span><span class="o">:</span>
        <span class="n">string</span> <span class="n">name</span><span class="p">;</span>
        <span class="n">vector</span><span class="o">&lt;</span><span class="n">MenuComponent</span><span class="o">*&gt;</span> <span class="n">menuComponents</span><span class="p">;</span>

        <span class="n">Menu</span><span class="p">(</span><span class="n">string</span> <span class="n">name</span><span class="p">)</span>
        <span class="p">{</span>
            <span class="k">this</span><span class="o">-&gt;</span><span class="n">name</span> <span class="o">=</span> <span class="n">name</span><span class="p">;</span>
        <span class="p">}</span>

        <span class="kt">void</span> <span class="n">add</span><span class="p">(</span><span class="n">MenuComponent</span> <span class="o">*</span><span class="n">menuComponent</span><span class="p">)</span>
        <span class="p">{</span>
            <span class="n">menuComponents</span><span class="p">.</span><span class="n">push_back</span><span class="p">(</span><span class="n">menuComponent</span><span class="p">);</span>
        <span class="p">}</span>
        <span class="n">string</span> <span class="n">getName</span><span class="p">(){</span><span class="k">return</span> <span class="n">name</span><span class="p">;}</span>

        <span class="n">MenuComponent</span><span class="o">*</span> <span class="n">getChild</span><span class="p">(</span><span class="kt">int</span> <span class="n">i</span><span class="p">)</span>
        <span class="p">{</span>
            <span class="k">return</span> <span class="n">menuComponents</span><span class="p">[</span><span class="n">i</span><span class="p">];</span>
        <span class="p">}</span>

        <span class="kt">void</span> <span class="n">print</span><span class="p">()</span>
        <span class="p">{</span>
            <span class="n">cout</span><span class="o">&lt;&lt;</span><span class="s">&quot;Name:  &quot;</span><span class="o">&lt;&lt;</span><span class="n">getName</span><span class="p">()</span><span class="o">&lt;&lt;</span><span class="n">endl</span><span class="p">;</span>
            <span class="n">cout</span><span class="o">&lt;&lt;</span><span class="s">&quot;--------------------------&quot;</span><span class="o">&lt;&lt;</span><span class="n">endl</span><span class="p">;</span>
            <span class="k">for</span><span class="p">(</span><span class="kt">int</span> <span class="n">i</span><span class="o">=</span><span class="mi">0</span><span class="p">;</span> <span class="n">i</span><span class="o">&lt;</span><span class="n">menuComponents</span><span class="p">.</span><span class="n">size</span><span class="p">();</span> <span class="n">i</span><span class="o">++</span><span class="p">)</span>
                <span class="n">menuComponents</span><span class="p">[</span><span class="n">i</span><span class="p">]</span><span class="o">-&gt;</span><span class="n">print</span><span class="p">();</span>
        <span class="p">}</span>
<span class="p">};</span>

<span class="k">class</span> <span class="nc">Test</span>
<span class="p">{</span>
    <span class="k">public</span><span class="o">:</span>
        <span class="n">MenuComponent</span><span class="o">*</span> <span class="n">menuComponent</span><span class="p">;</span>
        <span class="n">Test</span><span class="p">(</span><span class="n">MenuComponent</span><span class="o">*</span> <span class="n">menuComponent</span><span class="p">)</span>
        <span class="p">{</span>
            <span class="k">this</span><span class="o">-&gt;</span><span class="n">menuComponent</span> <span class="o">=</span> <span class="n">menuComponent</span><span class="p">;</span>
        <span class="p">}</span>

        <span class="kt">void</span> <span class="n">printout</span><span class="p">()</span> <span class="c">// handle the composite or leaf uniformly</span>
        <span class="p">{</span>
             <span class="n">cout</span><span class="o">&lt;&lt;</span><span class="s">&quot;Name: &quot;</span><span class="o">&lt;&lt;</span><span class="n">menuComponent</span><span class="o">-&gt;</span><span class="n">getName</span><span class="p">();</span>
             <span class="k">try</span>
             <span class="p">{</span>
                 <span class="n">cout</span><span class="o">&lt;&lt;</span><span class="s">&quot;  Price:&quot;</span><span class="o">&lt;&lt;</span><span class="n">menuComponent</span><span class="o">-&gt;</span><span class="n">getPrice</span><span class="p">();</span>
             <span class="p">}</span>
             <span class="k">catch</span><span class="p">(</span><span class="n">UnsupportedOperationException</span> <span class="n">error</span><span class="p">)</span>
             <span class="p">{</span>
             <span class="p">}</span>
             <span class="n">cout</span><span class="o">&lt;&lt;</span><span class="n">endl</span><span class="p">;</span>
        <span class="p">}</span>
<span class="p">};</span>


<span class="kt">int</span> <span class="n">main</span><span class="p">()</span>
<span class="p">{</span>

    <span class="n">MenuComponent</span> <span class="o">*</span><span class="n">menu</span><span class="p">;</span>
    <span class="n">Menu</span> <span class="n">a</span><span class="p">(</span><span class="s">&quot;Menu1&quot;</span><span class="p">);</span>
    <span class="n">Menu</span> <span class="n">b</span><span class="p">(</span><span class="s">&quot;Menu2&quot;</span><span class="p">);</span>
    <span class="n">MenuItem</span> <span class="n">item1</span><span class="p">(</span><span class="s">&quot;leaf1&quot;</span><span class="p">,</span> <span class="mf">23.2</span><span class="p">);</span>
    <span class="n">MenuItem</span> <span class="n">item2</span><span class="p">(</span><span class="s">&quot;leaf2&quot;</span><span class="p">,</span> <span class="mf">2.2</span><span class="p">);</span>

    <span class="n">menu</span> <span class="o">=</span> <span class="o">&amp;</span><span class="n">b</span><span class="p">;</span>
    <span class="n">menu</span><span class="o">-&gt;</span><span class="n">add</span><span class="p">(</span><span class="o">&amp;</span><span class="n">item1</span><span class="p">);</span>
    <span class="n">menu</span><span class="o">-&gt;</span><span class="n">add</span><span class="p">(</span><span class="o">&amp;</span><span class="n">item2</span><span class="p">);</span>

    <span class="n">menu</span> <span class="o">=</span> <span class="o">&amp;</span><span class="n">a</span><span class="p">;</span>
    <span class="n">menu</span><span class="o">-&gt;</span><span class="n">add</span><span class="p">(</span><span class="o">&amp;</span><span class="n">item1</span><span class="p">);</span>
    <span class="n">menu</span><span class="o">-&gt;</span><span class="n">add</span><span class="p">(</span><span class="o">&amp;</span><span class="n">item2</span><span class="p">);</span>

    <span class="n">menu</span><span class="o">-&gt;</span><span class="n">add</span><span class="p">(</span><span class="o">&amp;</span><span class="n">b</span><span class="p">);</span>
    <span class="n">menu</span><span class="o">-&gt;</span><span class="n">print</span><span class="p">();</span>

    <span class="n">cout</span><span class="o">&lt;&lt;</span><span class="s">&quot;######### Handle composite and leaf uniformly ########&quot;</span><span class="o">&lt;&lt;</span><span class="n">endl</span><span class="p">;</span>
    <span class="n">Test</span> <span class="n">t</span><span class="p">(</span><span class="o">&amp;</span><span class="n">a</span><span class="p">);</span>
    <span class="n">t</span><span class="p">.</span><span class="n">printout</span><span class="p">();</span>

    <span class="n">Test</span> <span class="n">s</span><span class="p">(</span><span class="o">&amp;</span><span class="n">item1</span><span class="p">);</span>
    <span class="n">s</span><span class="p">.</span><span class="n">printout</span><span class="p">();</span>
    <span class="k">return</span> <span class="mi">0</span><span class="p">;</span>
<span class="p">}</span>
</pre></div>
</td></tr></table></div>
<p>输出结果为:</p>
<div class="highlight-python"><pre>Name:  Menu1
--------------------------
Name:  leaf1  Price:23.2
Name:  leaf2  Price:2.2
Name:  Menu2
--------------------------
Name:  leaf1  Price:23.2
Name:  leaf2  Price:2.2
######### Handle composite and leaf uniformly ########
Name: Menu1
Name: leaf1  Price:23.2</pre>
</div>
</div>
<div class="section" id="id5">
<h2>面对新的需要<a class="headerlink" href="#id5" title="永久链接至标题">¶</a></h2>
<p>实现Composite基类中的相应接口即可.</p>
</div>
<div class="section" id="id6">
<h2>更多注意<a class="headerlink" href="#id6" title="永久链接至标题">¶</a></h2>
<p><strong>Composite模式</strong> 通常与 <a class="reference external" href="iterator.html#id1"><em>Iterator模式</em></a> 一起使用.</p>
</div>
<div class="section" id="id7">
<h2>参考更多<a class="headerlink" href="#id7" title="永久链接至标题">¶</a></h2>
<ol class="arabic simple">
<li><a class="reference external" href="http://en.wikipedia.org/wiki/Composite_pattern">Composite_Pattern</a></li>
</ol>
</div>
</div>


          </div>
        </div>
      </div>
      <div class="sphinxsidebar">
        <div class="sphinxsidebarwrapper">
            <h3><a href="../index.html">內容目录</a></h3>
            <ul>
<li><a class="reference external" href="">composite模式</a><ul>
<li><a class="reference external" href="#id1">composite模式定义</a></li>
<li><a class="reference external" href="#id3">问题描述</a></li>
<li><a class="reference external" href="#id4">具体代码</a></li>
<li><a class="reference external" href="#id5">面对新的需要</a></li>
<li><a class="reference external" href="#id6">更多注意</a></li>
<li><a class="reference external" href="#id7">参考更多</a></li>
</ul>
</li>
</ul>

            <h4>上一个主题</h4>
            <p class="topless"><a href="iterator.html"
                                  title="上一章">iterator模式</a></p>
            <h4>下一个主题</h4>
            <p class="topless"><a href="state.html"
                                  title="下一章">state模式</a></p>
            <h3>本页</h3>
            <ul class="this-page-menu">
              <li><a href="../_sources/designpattern/composite.txt"
                     rel="nofollow">显示源代码</a></li>
            </ul>
          <div id="searchbox" style="display: none">
            <h3>快速搜索</h3>
              <form class="search" action="../search.html" method="get">
                <input type="text" name="q" size="18" />
                <input type="submit" value="搜索" />
                <input type="hidden" name="check_keywords" value="yes" />
                <input type="hidden" name="area" value="default" />
              </form>
              <p class="searchtip" style="font-size: 90%">
              输入相关的模块，术语，类或者函数名称进行搜索
              </p>
          </div>
          <script type="text/javascript">$('#searchbox').show(0);</script>
        </div>
      </div>
      <div class="clearer"></div>
    </div>
    <div class="related">
      <h3>导航</h3>
      <ul>
        <li class="right" style="margin-right: 10px">
          <a href="../genindex.html" title="总目录"
             >索引</a></li>
        <li class="right" >
          <a href="state.html" title="state模式"
             >下一页</a> |</li>
        <li class="right" >
          <a href="iterator.html" title="iterator模式"
             >上一页</a> |</li>
        <li><a href="../index.html">programming v0.1 documentation</a> &raquo;</li>
          <li><a href="index.html" >设计模式学习笔记</a> &raquo;</li> 
      </ul>
    </div>
    <div class="footer">
      &copy; 版权所有 2009, zhutao.iscas@gmail.com.
      使用 <a href="http://sphinx.pocoo.org/">Sphinx</a> 0.6.1.
    </div>
  </body>
</html>